﻿/****************************************************************************
**
* @Project : Frameworks
* @File: aggregate.h
* @Description: 组件聚合管理类头文件，提供对象聚合和查询功能
* @Copyright: Copyright (c) 2014
* @Company:
* @WebSite: http://www.zchx.com/
* @author:
* @Revision History
* <pre>
* ----------------------------------------------------------------------
*   Ver     Date       Who        Comments
* ----- ----------  --------  ------------------------------------------
*   1.0  2013/08/12    yeguoxiong      FOR QT 5.1.0
* ----------------------------------------------------------------------
**
* @note 中文注释：组件聚合管理核心类，支持多对象聚合和类型安全查询
*       English: Core class for component aggregation management, supporting multi-object aggregation and type-safe queries
****************************************************************************/

#ifndef AGGREGATE_H
#define AGGREGATE_H

#include "extensionsystem_global.h"
#include <QObject>
#include <QList>
#include <QHash>
#include <QReadWriteLock>
#include <QReadLocker>
#include <QWriteLocker>
#include <QDebug>

namespace ExtensionSystem {

/**
 * @class Aggregate
 * @brief 组件聚合管理类
 * @details 用于聚合多个QObject派生类对象，提供类型安全的组件查询和管理功能
 *          支持动态添加/删除组件，并在组件变化时发射信号通知
 */
class EXTENSIONSYSTEM_EXPORT Aggregate : public QObject
{
    Q_OBJECT

public:
    /**
     * @brief 构造函数
     * @param parent 父对象指针
     * @details 创建Aggregate实例并初始化组件列表
     */
    Aggregate(QObject *parent = 0);
    
    /**
     * @brief 析构函数
     * @details 清理所有聚合的组件资源
     */
    virtual ~Aggregate();

    /**
     * @brief 添加组件到聚合管理器
     * @param component 要添加的组件对象指针
     * @details 将组件添加到内部列表，并建立对象生命周期管理
     */
    void add(QObject *component);
    
    /**
     * @brief 从聚合管理器移除组件
     * @param component 要移除的组件对象指针
     * @details 从内部列表移除组件，并断开相关连接
     */
    void remove(QObject *component);

    /**
     * @brief 查询指定类型的组件
     * @tparam T 要查询的组件类型
     * @return 匹配类型的组件指针，若不存在则返回nullptr
     * @details 使用qobject_cast进行类型安全查询，返回第一个匹配的组件
     */
    template <typename T> T *component()
    {
        QReadLocker(&lock());
        foreach (QObject *component, m_components)
        {
            if (T *result = qobject_cast<T *>(component))
            {
                return result;
            }
        }
        return (T *)0;
    }

    /**
     * @brief 查询所有指定类型的组件
     * @tparam T 要查询的组件类型
     * @return 匹配类型的组件列表
     * @details 返回所有符合类型要求的组件指针列表
     */
    template <typename T> QList<T *> components()
    {
        QReadLocker(&lock());
        QList<T *> results;
        foreach (QObject *component, m_components)
        {
            if (T *result = qobject_cast<T *>(component))
            {
                results << result;
            }
        }
        return results;
    }
    
    /**
     * @brief 获取对象所属的Aggregate实例
     * @param obj 要查询的对象指针
     * @return 对象所属的Aggregate指针，若不存在则返回nullptr
     */
    static Aggregate *parentAggregate(QObject *obj);
    
    /**
     * @brief 获取全局读写锁
     * @return 静态QReadWriteLock实例引用
     * @details 用于多线程环境下的组件操作同步
     */
    static QReadWriteLock &lock();
    
signals:
    /**
     * @brief 组件变化信号
     * @details 当组件添加或移除时发射，通知监听器更新
     */
    void changed();
    
private slots:
    /**
     * @brief 组件销毁时的自清理槽函数
     * @param obj 被销毁的组件对象
     * @details 当聚合的组件被销毁时自动调用，从列表中移除该组件
     */
    void deleteSelf(QObject *obj);

private:
    /**
     * @brief 获取对象到Aggregate的映射表
     * @return 静态QHash实例引用
     * @details 维护所有对象与Aggregate实例的关联关系
     */
    static QHash<QObject *, Aggregate *> &aggregateMap();

    QList<QObject *> m_components; ///< 聚合组件列表，存储所有添加的组件对象指针
}; // TODO: Qt5.15.2升级 - 考虑使用QObjectList替代QList<QObject*>以优化内存管理

template <typename T> T *query(Aggregate *obj)
{
    if (!obj) return (T *)0;
    return obj->template component<T>();
}

template <typename T> T *query(QObject *obj)
{
    if (!obj)
        return (T *)0;
    T *result = qobject_cast<T *>(obj);
    if (!result)
    {
        QReadLocker(&lock());
        Aggregate *parentAggregation = Aggregate::parentAggregate(obj);
        result = (parentAggregation ? query<T>(parentAggregation) : 0);
    }
    return result;
}

template <typename T> QList<T *> query_all(Aggregate *obj)
{
    if (!obj)
        return QList<T *>();
    return obj->template components<T>();
}

template <typename T> QList<T *> query_all(QObject *obj)
{
    if (!obj)
        return QList<T *>();
    QReadLocker(&lock());
    Aggregate *parentAggregation = Aggregate::parentAggregate(obj);
    QList<T *> results;
    if (parentAggregation)
    {
        results = query_all<T>(parentAggregation);
    }else if (T *result = qobject_cast<T *>(obj))
    {
        results.append(result);
    }
    return results;
}

} // namespace ExtensionSystem

#endif // AGGREGATE_H
